package com.yupi.springbootinit.statemachine.step.impl;

import com.yupi.springbootinit.model.enums.StepEvent;
import com.yupi.springbootinit.model.enums.StepStatus;
import com.yupi.springbootinit.statemachine.step.StepStateMachine;
import com.yupi.springbootinit.statemachine.step.StepTransitionContext;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

import static com.yupi.springbootinit.model.enums.StepEvent.*;
import static com.yupi.springbootinit.model.enums.StepStatus.*;

/**
 * 默认步骤状态机实现（骨架）
 * 规则：
 * - PLANNED --(MAKE_READY)--> READY  [要求 previousCompleted=true 或由PMC手动推动]
 * - READY --(START)--> IN_PROGRESS   [若 now > planStart+5min，必须提供 overdueReason]
 * - IN_PROGRESS --(COMPLETE)--> (needInspection==1 ? PENDING_QA : COMPLETED)
 * - PENDING_QA --(QA_PASS)--> COMPLETED
 * - PENDING_QA --(QA_FAIL)--> READY
 */
public class DefaultStepStateMachine implements StepStateMachine {

    private static final long OVERDUE_MINUTES = 5L;

    @Override
    public boolean canTransit(StepStatus from, StepEvent event, StepTransitionContext ctx) {
        if (from == null || event == null) return false;

        // 静态可达性
        boolean allowed = allowedEvents(from, ctx).contains(event);
        if (!allowed) return false;

        // 守卫：READY -> START 的逾期原因校验
        if (from == READY && event == START) {
            LocalDateTime now = ctx != null && ctx.getNow() != null ? ctx.getNow() : LocalDateTime.now();
            LocalDateTime planStart = ctx != null ? ctx.getPlanStart() : null;
            if (planStart != null && now.isAfter(planStart.plusMinutes(OVERDUE_MINUTES))) {
                return ctx != null && StringUtils.isNotBlank(ctx.getOverdueReason());
            }
        }

        // 守卫：PLANNED -> READY 需前序完成或管理推动
        if (from == PLANNED && event == MAKE_READY) {
            Boolean prev = ctx != null ? ctx.getPreviousCompleted() : null;
            // 允许通过：前序完成 或 外部明确放行（prev==null 也允许，由外层控制）
            return prev == null || Boolean.TRUE.equals(prev);
        }

        return true;
    }

    @Override
    public StepStatus transit(StepStatus from, StepEvent event, StepTransitionContext ctx) {
        if (!canTransit(from, event, ctx)) {
            throw new IllegalStateException("非法步骤流转: from=" + from + ", event=" + event);
        }
        switch (from) {
            case PLANNED:
                if (event == MAKE_READY) {
                    return READY;
                }
                throw new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
            case READY:
                if (event == START) {
                    return IN_PROGRESS;
                }
                throw new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
            case IN_PROGRESS:
                if (event == COMPLETE) {
                    Integer needInspection = ctx != null ? ctx.getNeedInspection() : null;
                    boolean need = needInspection != null && needInspection == 1;
                    return need ? PENDING_QA : COMPLETED;
                }
                throw new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
            case PENDING_QA:
                if (event == QA_PASS) {
                    return COMPLETED;
                }
                if (event == QA_FAIL) {
                    return READY;
                }
                throw new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
            case COMPLETED:
                throw new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
            default:
                throw new IllegalStateException("未知状态: " + from);
        }
    }

    @Override
    public List<StepEvent> allowedEvents(StepStatus from, StepTransitionContext ctx) {
        return switch (from) {
            case PLANNED -> List.of(MAKE_READY);
            case READY -> List.of(START);
            case IN_PROGRESS -> List.of(COMPLETE);
            case PENDING_QA -> List.of(QA_PASS, QA_FAIL);
            case COMPLETED -> List.of();
        };
    }

    private IllegalStateException throwISE(StepStatus from, StepEvent event) {
        return new IllegalStateException("不支持的步骤流转: from=" + from + ", event=" + event);
    }
}